package com.java.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.java.enums.LendStatusEnum;
import com.java.enums.TransTypeEnum;
import com.java.exceptioin.Assert;
import com.java.hfb.FormHelper;
import com.java.hfb.HfbConst;
import com.java.hfb.RequestHelper;
import com.java.mapper.*;
import com.java.pojo.bo.TransFlowBO;
import com.java.pojo.entity.*;
import com.java.result.ResponseEnum;
import com.java.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.java.utils.LendNoUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 还款记录表 服务实现类
 * </p>
 *
 * @author Helen
 * @since 2021-07-08
 */
@Service
public class LendReturnServiceImpl extends ServiceImpl<LendReturnMapper, LendReturn> implements LendReturnService {

    private static final Logger log1 = LoggerFactory.getLogger(LendReturnServiceImpl.class);
    @Resource
    private LendReturnMapper lendReturnMapper;

    @Resource
    private UserAccountService userAccountService;

    @Resource
    private LendMapper lendMapper;

    @Resource
    private UserBindService userBindService;

    @Resource
    private LendItemReturnService lendItemReturnService;

    @Resource
    private UserInfoMapper userInfoMapper;

    @Resource
    private TransFlowService transFlowService;

    @Resource
    private LendItemReturnMapper lendItemReturnMapper;

    @Resource
    private LendItemMapper lendItemMapper;

    //还款计划
    @Override
    public List<LendReturn> selectByLendId(Long lendId) {
        QueryWrapper<LendReturn> wrapper = new QueryWrapper<>();
        wrapper.eq("lend_id",lendId);
        return lendReturnMapper.selectList(wrapper);
    }

    //还款
    @Override
    public String commitLendItem(Long lendReturnId, Long userId) {

        LendReturn lendReturn = lendReturnMapper.selectById(lendReturnId);
        //根据lendId查询lend
        Lend lend = lendMapper.selectById(lendReturn.getLendId());
        String bindCode = userBindService.getBindCodeByUserId(userId);


        //查询
        BigDecimal amount = userAccountService.getAmount(userId);
        //校验还款的余额是否比账户余额小
        Assert.isTrue(amount.doubleValue() >=  lendReturn.getPrincipal().doubleValue(), ResponseEnum.NOT_SUFFICIENT_FUNDS_ERROR);

        //组装数据
        Map<String, Object> param = new HashMap<>();
        param.put("agentId", HfbConst.AGENT_ID);
        //流水编号
        param.put("agentGoodsName", lend.getTitle());
        //批次号。数字、字母组成 lendReturnNo
        param.put("agentBatchNo", lendReturn.getReturnNo());
        //还款人协议号
        param.put("fromBindCode", bindCode);
        //还款总额
        param.put("totalAmt", lendReturn.getTotal());
        //还款明细
        List<Map<String,Object>> lendItemReturnDetailList = lendItemReturnService.getLendItemReturnDetail(lendReturn.getId());
        //还款明细数据，json格式。目前一次最多支持100个单。
        param.put("data", JSONObject.toJSONString(lendItemReturnDetailList));
        //手续费
        param.put("voteFeeAmt", new BigDecimal(0));
        //返回地址
        param.put("returnUrl", HfbConst.BORROW_RETURN_RETURN_URL);
        param.put("notifyUrl", HfbConst.BORROW_RETURN_NOTIFY_URL);
        param.put("timestamp", RequestHelper.getTimestamp());
        param.put("sign", RequestHelper.getSign(param));
        //将数据组装到表单
        String buildForm = FormHelper.buildForm(HfbConst.BORROW_RETURN_URL,param);
        return buildForm;
    }

    //还款回调
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void notifyUrl(Map<String, Object> map) {

        //还款编号
        String agentBatchNo = (String)map.get("agentBatchNo");
        //幂等性判断 标准：判断交易流水是否存在
        Boolean isSaveTransFlow = transFlowService.isSaveTransFlow(agentBatchNo);
        if(isSaveTransFlow){
            log1.info("已存在");
            return;
        }

        QueryWrapper<LendReturn> wrapper = new QueryWrapper<>();
        wrapper.eq("return_no",agentBatchNo);
        LendReturn lendReturn = lendReturnMapper.selectOne(wrapper);
        //更新还款状态 还款时间
        lendReturn.setStatus(1);
        lendReturn.setRealReturnTime(LocalDateTime.now());
        lendReturnMapper.updateById(lendReturn);

        //更新标的状态
        Lend lend = lendMapper.selectById(lendReturn.getLendId());
        if(lendReturn.getLast()){
            lend.setStatus(LendStatusEnum.PAY_OK.getStatus());
            lendMapper.updateById(lend);
        }
        BigDecimal totalAmt = new BigDecimal((String)map.get("totalAmt")) ;
        //借款账号转出金额
        //根据借款人id查询bindCode 根据bindCode 和 转出金额更新借款人账户信息
        String bindCode = userBindService.getBindCodeByUserId(lend.getUserId());
        userInfoMapper.updateAmount(bindCode,totalAmt.negate(),new BigDecimal(0));

        //借款人交易流水
        TransFlowBO transFlowBO = new TransFlowBO(
                agentBatchNo,
                bindCode,
                totalAmt,
                TransTypeEnum.RETURN_DOWN,
                "借款人还款扣减，项目编号：" + lend.getLendNo() + "，项目名称：" + lend.getTitle());
        transFlowService.saveTransFlow(transFlowBO);

        //更新回款明细
        //根据还款id获取当前每个投资人的回款明细
        List<LendItemReturn> lendItemReturnList = lendItemReturnService.selectLendItemReturnList(lendReturn.getId());
        lendItemReturnList.forEach(item->{
            //TODO
            //更新回款记录状态
            item.setStatus(1);
            lendItemReturnMapper.updateById(item);

            //更新出借信息
            LendItem lendItem = lendItemMapper.selectById(item.getLendItemId());
            lendItem.setRealAmount(lendItem.getRealAmount().add(item.getInterest()));
            lendItemMapper.updateById(lendItem);

            String investBindCode = userBindService.getBindCodeByUserId(item.getInvestUserId());
            //投资账号转入金额
            userInfoMapper.updateAmount(investBindCode,item.getTotal(),new BigDecimal(0));

            //投资账号交易流水
            TransFlowBO investTransFlowBO = new TransFlowBO(
                    LendNoUtils.getReturnItemNo(),
                    investBindCode,
                    item.getTotal(),
                    TransTypeEnum.INVEST_BACK,
                    "还款到账，项目编号：" + lend.getLendNo() + "，项目名称：" + lend.getTitle());
            transFlowService.saveTransFlow(investTransFlowBO);
        });
    }
}
